<template>
  <div class="login-auth">
    <div class="slider-container"
         @mousedown="startDrag" @mousemove="handleDrag"
         @mouseup="endDrag" @mouseleave="endDrag"
         @touchstart="startDrag" @touchmove="handleDrag" @touchend="endDrag">
      <div ref="draggableRef" class="draggable"
           :style="{ left: `${loginAuth.dragLeft}px` }">
        <i v-if="authStore.isVerified" class="fas fa-check"></i>
        <i v-else class="fas fa-arrow-right"></i>
      </div>
      <div :style="{ width: loginAuth.progressWidth + '%' }" class="slider-progress"></div>
      <div class="slider-message" :style="{color: authStore.isVerified ? '#FFFFFF' : '#696969'}">
        <span v-if="authStore.isVerified">验证成功！</span>
        <span v-else-if="loginAuth.isDragging">拖动中...</span>
        <span v-else>向右拖动滑块 完成验证</span>
      </div>
    </div>
  </div>
</template>

<script setup>
import { reactive, ref } from 'vue'
import { useAuthStore } from '@/store/auth'

const draggableRef = ref(null)
const authStore = useAuthStore()

const loginAuth = reactive({
  isDragging: false,
  initialX: 0,
  offsetX: 0,
  dragLeft: 0,
  progressWidth: 0,
  targetWidth: 100,
  // 记录拖动的开始时间
  startTime: 0,
  // 记录拖动过程中的位置
  positions: [],
  // 记录拖动过程中的时间戳
  timestamps: []
})

const startDrag = (event) => {
  // 验证成功后禁止拖动
  if (authStore.isVerified) return
  loginAuth.isDragging = true

  const touch = event.changedTouches ? event.changedTouches[0] : event
  loginAuth.initialX = touch.clientX
  loginAuth.offsetX = draggableRef.value?.offsetLeft

  loginAuth.startTime = Date.now()
  loginAuth.positions = []
  loginAuth.timestamps = []
  loginAuth.positions.push(loginAuth.initialX)
  loginAuth.timestamps.push(loginAuth.startTime)
}

const handleDrag = (event) => {
  if (loginAuth.isDragging && !authStore.isVerified) {
    const touch = event.changedTouches ? event.changedTouches[0] : event
    const dx = touch.clientX - loginAuth.initialX
    const newLeft = loginAuth.offsetX + dx
    const sliderWidth = draggableRef.value?.parentNode.offsetWidth
    const handleWidth = draggableRef.value?.offsetWidth

    if (newLeft < 0) {
      loginAuth.dragLeft = 0
      loginAuth.progressWidth = 0
    } else if (newLeft > sliderWidth - handleWidth) {
      loginAuth.dragLeft = sliderWidth - handleWidth
      loginAuth.progressWidth = loginAuth.targetWidth
    } else {
      loginAuth.dragLeft = newLeft
      loginAuth.progressWidth = (newLeft / (sliderWidth - handleWidth)) * loginAuth.targetWidth
    }

    loginAuth.positions.push(touch.clientX)
    loginAuth.timestamps.push(Date.now())
  }
}

const endDrag = () => {
  loginAuth.isDragging = false
  if (loginAuth.progressWidth === loginAuth.targetWidth && !checkIsHuman()) {
    authStore.isVerified = true
  } else {
    loginAuth.dragLeft = 0
    loginAuth.progressWidth = 0
  }
}

const checkIsHuman = () => {
  const endTime = Date.now()
  const dragDuration = endTime - loginAuth.startTime

  const speedChanges = []
  for (let i = 1; i < loginAuth.positions.length; i++) {
    const distance = loginAuth.positions[i] - loginAuth.positions[i - 1]
    const time = loginAuth.timestamps[i] - loginAuth.timestamps[i - 1]
    const speed = time > 0 ? distance / time : 0
    speedChanges.push(speed)
  }

  // 计算速度变化的标准差
  const meanSpeed = speedChanges.reduce((sum, speed) => sum + speed, 0) / speedChanges.length
  const variance = speedChanges.reduce((sum, speed) => sum + Math.pow(speed - meanSpeed, 2), 0) / speedChanges.length
  const stdDevSpeed = Math.sqrt(variance)

  // 检查是否有停顿
  let hasPause = false
  for (let i = 1; i < loginAuth.timestamps.length; i++) {
    if (loginAuth.timestamps[i] - loginAuth.timestamps[i - 1] > 200) {
      hasPause = true
      break
    }
  }

  // 综合判断是否为机器操作
  return dragDuration >= 100 && stdDevSpeed >= 0.1 && hasPause
}
</script>

<style lang="scss">
.login-auth {
  width: 100%;

  .slider-container {
    position: relative;
    height: 32px;
    background-color: #E7E9E8;
    border: 1px solid #E7E9E8;
    border-radius: 5px;
    overflow: hidden;

    .draggable {
      position: absolute;
      top: 0;
      left: 0;
      width: 35px;
      height: 32px;
      display: flex;
      justify-content: center;
      align-items: center;
      background-color: var(--el-color-primary);
      color: #FFFFFF;
      cursor: pointer;
      z-index: 3;
      border-left: 1px solid #E7E9E8;
      border-radius: 3px;
    }

    .slider-progress {
      position: absolute;
      top: 0;
      left: 0;
      height: 100%;
      background-color: var(--el-color-primary);
      z-index: 1;
    }

    .slider-message {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      z-index: 2;
      user-select: none;

      span {
        transition: opacity 0.3s ease;
        opacity: 1;
      }
    }
  }
}
</style>
